import { MsgEnum } from '@/enums'
/**
 * 文件大小格式化
 */
export const formatBytes = (bytes: number): string => {
  if (bytes === 0 || !bytes) {
    return '0 B'
  }

  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  const base = 1024
  const unitIndex = Math.floor(Math.log(bytes) / Math.log(base))
  const size = parseFloat((bytes / Math.pow(base, unitIndex)).toFixed(2))

  return size + ' ' + units[unitIndex]
}

/**
 * 图片尺寸格式化
 * @param width 图片宽度
 * @param height 图片高度
 * @param option 选项: { maxWidth: number, maxHeight: number }
 */
export const formatImage = (
  width: number,
  height: number,
  option = {
    maxWidth: 200,
    maxHeight: 150,
  },
): number => {
  const { maxWidth, maxHeight } = option
  // 小： 如果图片宽高都小于最大宽高，直接返回原高度
  if (width < maxWidth && height < maxHeight) {
    return height
    // 宽： 根据宽度等比缩放
  } else if (width > height) {
    return (maxWidth / width) * height
    // 窄：返回最大高度
  } else if (width === height || width < height) {
    return maxHeight
  }
  return maxHeight
}

/** 注意！这是文件图标映射关系表，如有修改需求-请联系前端管理同学 */
const fileSuffixMap: Record<string, string> = {
  'jpg': 'jpg',
  'jpeg': 'jpg',
  'png': 'jpg',
  'webp': 'jpg',
  'mp4': 'mp4',
  'mov': 'mp4',
  'avi': 'mp4',
  'rmvb': 'mp4',
  'doc': 'doc',
  'docx': 'doc',
  'mp3': 'mp3',
  'wav': 'mp3',
  'aac': 'mp3',
  'flac': 'mp3',
  'pdf': 'pdf',
  'ppt': 'ppt',
  'pptx': 'ppt',
  'xls': 'xls',
  'xlsx': 'xls',
  'zip': 'zip',
  'rar': 'zip',
  '7z': 'zip',
  'txt': 'txt',
  'log': 'log',
  'svg': 'svg',
  'sketch': 'sketch',
  'exe': 'exe',
  'md': 'md',
}
/**
 * 获取文件对应的Icon
 * @param fileName 文件名
 * @returns Icon
 */
export const getFileSuffix = (fileName: string): string => {
  if (!fileName) return 'other'

  const suffix = fileName.toLowerCase().split('.').pop()
  if (!suffix) return 'other'

  return fileSuffixMap[suffix] || 'other'
}

// 生成消息体
export const generateBody = (fileInfo: any, msgType: MsgEnum, isMock?: boolean) => {
  const {
    size,
    width,
    height,
    downloadUrl,
    name,
    second,
    tempUrl,
    thumbWidth,
    thumbHeight,
    thumbUrl,
    thumbSize,
  } = fileInfo
  const url = isMock ? tempUrl : downloadUrl
  const baseBody = { size, url }
  let body = {}

  if (msgType === MsgEnum.IMAGE) {
    body = { ...baseBody, width, height }
  } else if (msgType === MsgEnum.VOICE) {
    body = { ...baseBody, second }
  } else if (msgType === MsgEnum.VIDEO) {
    body = { ...baseBody, thumbWidth, thumbHeight, thumbUrl, thumbSize }
  } else if (msgType === MsgEnum.FILE) {
    body = { ...baseBody, fileName: name, url: downloadUrl }
  }
  return { body, type: msgType }
}

/**
 * 地址转Blob
 */
export const urlToBlob = async (url: string): Promise<Blob> => {
  const response = await fetch(url)
  const blob = await response.blob()
  return blob
}

/**
 * 地址转文件
 */
export const urlToFile = async (url: string, fileName?: string): Promise<File> => {
  const blob = await urlToBlob(url)
  const fileType = blob.type
  const name = fileName || Date.now() + '_emoji.png' // 时间戳生成唯一文件名
  const file = new File([blob], name, { type: fileType })
  return file
}

import { isArray, isNumber, isString, orderBy } from 'lodash-es'
import { resolveComponent } from 'vue'
import dayjs from 'dayjs'

export * from './loading'
// 首字母大写
export function firstUpperCase(value: string): string {
  return value.replace(/\b(\w)(\w*)/g, ($0, $1, $2) => {
    return $1.toUpperCase() + $2
  })
}

// 获取方法名
export function getNames(value: any) {
  return Object.getOwnPropertyNames(value.constructor.prototype)
}

// 获取地址栏参数
export function getUrlParam(name: string): string | null {
  const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`)
  const r = window.location.search.substr(1).match(reg)
  if (r != null) {
    return decodeURIComponent(r[2])
  }
  return null
}

// 文件名
export function filename(path: string): string {
  return basename(path.substring(0, path.lastIndexOf('.')))
}

// 路径名称
export function basename(path: string): string {
  let index = path.lastIndexOf('/')
  index = index > -1 ? index : path.lastIndexOf('\\')
  if (index < 0) {
    return path
  }
  return path.substring(index + 1)
}

// 文件扩展名
export function extname(path: string): string {
  return path.substring(path.lastIndexOf('.') + 1).split(/(\?|&)/)[0]
}

// 横杠转驼峰
export function toCamel(str: string): string {
  return str.replace(/([^-])(?:-+([^-]))/g, ($0, $1, $2) => {
    return $1 + $2.toUpperCase()
  })
}

// uuid
export function uuid(separator = '-'): string {
  const s: any[] = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4'
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1)
  s[8] = s[13] = s[18] = s[23] = separator

  return s.join('')
}

// 浏览器信息
export function getBrowser() {
  const { clientHeight, clientWidth } = document.documentElement

  // 浏览器信息
  const ua = navigator.userAgent.toLowerCase()

  // 浏览器类型
  let type = (ua.match(/firefox|chrome|safari|opera/g) || 'other')[0]

  if ((ua.match(/msie|trident/g) || [])[0]) {
    type = 'msie'
  }

  // 平台标签
  let tag = ''

  const isTocuh = 'ontouchstart' in window || ua.includes('touch') || ua.includes('mobile')
  if (isTocuh) {
    if (ua.includes('ipad')) {
      tag = 'pad'
    } else if (ua.includes('mobile')) {
      tag = 'mobile'
    } else if (ua.includes('android')) {
      tag = 'androidPad'
    } else {
      tag = 'pc'
    }
  } else {
    tag = 'pc'
  }

  // 浏览器内核
  let prefix = ''

  switch (type) {
    case 'chrome':
    case 'safari':
    case 'mobile':
      prefix = 'webkit'
      break
    case 'msie':
      prefix = 'ms'
      break
    case 'firefox':
      prefix = 'Moz'
      break
    case 'opera':
      prefix = 'O'
      break
    default:
      prefix = 'webkit'
      break
  }

  // 操作平台
  const plat = ua.indexOf('android') > 0 ? 'android' : navigator.platform.toLowerCase()

  // 屏幕信息
  let screen = 'full'

  if (clientWidth < 768) {
    screen = 'xs'
  } else if (clientWidth < 992) {
    screen = 'sm'
  } else if (clientWidth < 1200) {
    screen = 'md'
  } else if (clientWidth < 1920) {
    screen = 'xl'
  } else {
    screen = 'full'
  }

  // 是否 ios
  const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)

  // 浏览器版本
  const version = (ua.match(/[\s\S]+(?:rv|it|ra|ie)[/: ]([\d.]+)/) || [])[1]

  // 是否 PC 端
  const isPC = tag === 'pc'

  // 是否移动端
  const isMobile = !isPC

  // 是否移动端 + 屏幕宽过小
  const isMini = screen === 'xs' || isMobile

  return {
    height: clientHeight,
    width: clientWidth,
    version,
    type,
    plat,
    tag,
    prefix,
    isMobile,
    isIOS,
    isPC,
    isMini,
    screen,
  }
}

// 路径转数组
export function deepPaths(paths: string[], splitor?: string) {
  const list: any[] = []

  paths.forEach((e) => {
    const arr: string[] = e.split(splitor || '/').filter(Boolean)

    let c = list

    arr.forEach((a, i) => {
      let d = c.find((e) => e.label === a)

      if (!d) {
        d = {
          label: a,
          value: a,
          children: arr[i + 1] ? [] : null,
        }

        c.push(d)
      }

      if (d.children) {
        c = d.children
      }
    })
  })

  return list
}

// 列表转树形
export function deepTree(list: any[], sort?: 'desc' | 'asc'): any[] {
  const newList: any[] = []
  const map: any = {}

  orderBy(list, 'orderNum', sort)
    .map((e) => {
      map[e.id] = e
      return e
    })
    .forEach((e) => {
      const parent = map[e.parentId]

      if (parent) {
        ;(parent.children || (parent.children = [])).push(e)
      } else {
        newList.push(e)
      }
    })

  return newList
}

// 树形转列表
export function revDeepTree(list: any[]) {
  const arr: any[] = []
  let id = 0

  function deep(list: any[], parentId: number) {
    list.forEach((e) => {
      if (!e.id) {
        e.id = ++id
      }

      if (!e.parentId) {
        e.parentId = parentId
      }

      arr.push(e)

      if (e.children && isArray(e.children) && e.id) {
        deep(e.children, e.id)
      }
    })
  }

  deep(list || [], 0)

  return arr
}

// 路径转对象
export function path2Obj(list: any[]) {
  const data: any = {}

  list.forEach(({ path, value }) => {
    if (path) {
      const arr: string[] = path.split('/')
      const parents = arr.slice(0, arr.length - 1)
      const name = basename(path).replace('.ts', '')

      let curr = data

      parents.forEach((k) => {
        if (!curr[k]) {
          curr[k] = {}
        }

        curr = curr[k]
      })

      curr[name] = value
    }
  })

  return data
}

// 是否是组件
export function isComponent(name: string) {
  return !isString(resolveComponent(name))
}

// 是否Promise
export function isPromise(val: any) {
  return val && Object.prototype.toString.call(val) === '[object Promise]'
}

// 单位转换
export function parsePx(val: string | number) {
  return isNumber(val) ? `${val}px` : val
}

// 延迟
export function sleep(duration: number) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, duration)
  })
}

// 描述时间差
export function describeTimeDifference(timestamp: Date | undefined) {
  if (!timestamp) {
    return '--'
  }
  const now = dayjs() // 当前时间
  const past = dayjs(timestamp) // 过去时间
  if (now.isBefore(past)) {
    return '未来的时间'
  }

  // 判断同年同月通天
  if (now.isSame(past, 'day')) {
    const oneMinuteAgo = now.subtract(1, 'minute')
    if (past >= oneMinuteAgo) {
      return '刚刚'
    }
    return dayjs(past).format('HH:mm')
  } else if (now.isSame(past, 'month')) {
    // 判断同年同月
    if (now.subtract(1, 'day').isSame(past, 'day')) {
      // 判断相差一天
      return '昨天'
    } else if (now.subtract(2, 'day').isSame(past, 'day')) {
      // 判断相差两天
      return '前天'
    }
  }
  return dayjs(past).format('YY-MM-DD')
}

// 获取地理位置
export const getCurrentLocation = () => {
  let location={longitude:-1,latitude:-1}
    if (navigator.geolocation) {
      navigator.geolocation.watchPosition(
       function(position){
         location.longitude = position.coords.longitude
         location.latitude = position.coords.latitude
         localStorage.setItem('location',JSON.stringify(location))
       },
       function(error){
         console.error('error=>',error)
       },
       {
         enableHighAccuracy: true, // Use high accuracy
         // timeout: 20000, // 10 seconds timeout
         maximumAge: 0 // Re
       }
     )
   } else {
     console.error('Geolocation is not supported by this browser.')
   }

}